package com.oauth.google.server.picasa.service;

import java.net.URL;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;

import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthSigner;
import com.google.gdata.client.photos.PicasawebService;
import com.google.gdata.data.photos.AlbumFeed;
import com.google.gdata.data.photos.GphotoEntry;
import com.google.gdata.data.photos.GphotoFeed;
import com.google.gdata.data.photos.PhotoEntry;
import com.google.gdata.data.photos.UserFeed;
import com.oauth.common.server.beans.OAuthAccessToken;
import com.oauth.common.server.beans.OAuthConfigBean;
import com.oauth.common.server.beans.OAuthRequestToken;
import com.oauth.google.client.beans.picassa.GooglePicasaAlbum;
import com.oauth.google.client.beans.picassa.PicasaPhoto;
import com.oauth.google.server.beans.GooglePicasaBean;
import com.oauth.google.server.beans.GoogleRequestToken;
import com.oauth.google.server.constants.GoogleServiceType;
import com.oauth.google.server.picasa.util.PicasaUtils;
import com.oauth.service.generic.OAuthService;
import com.oauth.service.generic.beans.OAuthServiceBean;

public class PicasaOAuthServiceImpl implements PicasaOAuthService {

	private GoogleOAuthHelper mOAuthHelper;
	private OAuthSigner mSigner;
	private OAuthService mOAuthService;
	private OAuthConfigBean mOAuthConfigBean;

	@PostConstruct
	public void initialise() {
		mSigner = new OAuthHmacSha1Signer();
		mOAuthHelper = new GoogleOAuthHelper(mSigner);
	}

	/**
	 * @param pOAuthService
	 *            the oAuthService to set
	 */
	@Autowired(required = true)
	public void setOAuthService(OAuthService pOAuthService) {
		mOAuthService = pOAuthService;
	}

	/**
	 * @param pOAuthConfigBean
	 *            the oAuthConfigBean to set
	 */
	@Required
	public void setOAuthConfigBean(OAuthConfigBean pOAuthConfigBean) {
		mOAuthConfigBean = pOAuthConfigBean;
	}

	private GoogleOAuthParameters getOAuthParameters() {
		GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
		oauthParameters.setOAuthConsumerKey(mOAuthConfigBean.getConsumerKey());
		oauthParameters.setOAuthConsumerSecret(mOAuthConfigBean
				.getConsumerSecret());
		oauthParameters.setScope(GoogleServiceType.Picasa.getScope());
		return oauthParameters;
	}

	private PicasawebService getPicasaService(Long pMemberId) throws Exception {
		GoogleOAuthParameters oauthParameters = getOAuthParameters();
		OAuthAccessToken accessToken = getAccessTokenFromDB(pMemberId);
		oauthParameters.setOAuthToken(accessToken.getToken());
		oauthParameters.setOAuthTokenSecret(accessToken.getTokenSecret());

		PicasawebService picasaService = new PicasawebService(
				GoogleServiceType.Picasa.getGoogleServiceName());
		// Set the OAuth credentials which were obtained from the step
		picasaService.setOAuthCredentials(oauthParameters, mSigner);
		return picasaService;
	}

	private <F extends GphotoFeed<F>> F getFeed(
			PicasawebService pPicasaService, Class<F> pClass) throws Exception {
		URL feedUrl = new URL(GoogleServiceType.Picasa.getFeedUrl());
		return pPicasaService.getFeed(feedUrl, pClass);
	}

	private <F extends GphotoFeed<F>> F getFeed(String pFeedUrl,
			Class<F> pClass, PicasawebService pPicasaService) throws Exception {
		URL feedUrl = new URL(pFeedUrl);
		return pPicasaService.getFeed(feedUrl, pClass);
	}

	@Override
	public OAuthAccessToken getAccessTokenFromDB(Long pMemberId)
			throws Exception {
		OAuthServiceBean token = null;
		token = mOAuthService.getToken(pMemberId, GooglePicasaBean.class);
		if (token != null) {
			return new OAuthAccessToken(token.getAccessToken(), token
					.getAccessTokenSecret());
		}
		return null;
	}

	@Override
	public OAuthAccessToken getAccessTokenFromRequestToken(
			OAuthRequestToken pRequestToken, String pQueryString)
			throws Exception {
		GoogleOAuthParameters oauthParameters = getOAuthParameters();
		mOAuthHelper.getOAuthParametersFromCallback(pQueryString,
				oauthParameters);
		oauthParameters.setOAuthToken(pRequestToken.getToken());
		oauthParameters.setOAuthTokenSecret(pRequestToken.getTokenSecret());
		// Get access token .
		String accessToken = mOAuthHelper.getAccessToken(oauthParameters);
		return new OAuthAccessToken(accessToken, oauthParameters
				.getOAuthTokenSecret());
	}

	@Override
	public GoogleRequestToken getRequestToken() throws Exception {
		GoogleOAuthParameters oauthParameters = getOAuthParameters();
		mOAuthHelper.getUnauthorizedRequestToken(oauthParameters);
		oauthParameters.setOAuthCallback(mOAuthConfigBean.getCallBackUrl());
		String authorizeUrl = mOAuthHelper
				.createUserAuthorizationUrl(oauthParameters);
		GoogleRequestToken oauthTokenBean = new GoogleRequestToken(
				oauthParameters.getOAuthToken(), oauthParameters
						.getOAuthTokenSecret(), authorizeUrl);
		return oauthTokenBean;
	}

	@Override
	public void persistAccessToken(OAuthAccessToken pAccessToken, Long pMemberId)
			throws Exception {
		GooglePicasaBean serviceBean = new GooglePicasaBean();
		serviceBean.setAccessToken(pAccessToken.getToken());
		serviceBean.setAccessTokenSecret(pAccessToken.getTokenSecret());
		serviceBean.setMemberId(pMemberId);
		// serviceBean.setTwitterId(twitter.getUserId());
		mOAuthService.persistToken(serviceBean); // persist in db for future
		// use.
	}

	@Override
	public List<GooglePicasaAlbum> getPicasaAlbums(Long pMemberId)
			throws Exception {
		PicasawebService picasaService = getPicasaService(pMemberId);
		UserFeed feed = getFeed(GoogleServiceType.Picasa.getFeedUrl()
				+ "?kind=album", UserFeed.class, picasaService);
		List<GphotoEntry> entries = feed.getEntries();
		return PicasaUtils.getPicasaAlbums(entries);
	}

	@Override
	public List<PicasaPhoto> getPhotosForAlbum(Long pMemberId, String pAlbumId)
			throws Exception {
		PicasawebService picasaService = getPicasaService(pMemberId);
		AlbumFeed feed = getFeed(GoogleServiceType.Picasa.getFeedUrl()
				+ "/albumid/" + pAlbumId, AlbumFeed.class, picasaService);
		List<PhotoEntry> photos = feed.getPhotoEntries();
		return PicasaUtils.getPhotos(photos);
	}

}
